# @argument(a__str=1, b__int=1, c__int=0)
# def my_view(username, age, gender):
#     pass
#
# my_view(username="sdfsdf",  gender="1")

# def argument(**kwargs_d):
#     arg_list = []
#     for key, value in kwargs_d.items():
#         if value == 1:
#             arg_list.append(key.split('__')[0])
#
#     def wrapper(method):
#         def my_view(**kwargs):
#             for i in arg_list:
#                 #new_list = [key_1 for key_1 in kwargs]
#                 if i not in kwargs.keys():
#                     raise Exception('ERROR', i)
#             for key_0, value_0 in kwargs.items():
#                 if key_0 == 'username':
#                     kwargs[key_0] = str(value_0)
#
#                 elif key_0 == 'age' or key_0 == 'gender':
#                     kwargs[key_0] = int(value_0)
#
#             return method(**kwargs)
#
#         return my_view
#
#     return wrapper

def argument_validator(**kwargs_template):
    template = {}
    for k, v in kwargs_template.items():
        arg_name, arg_type = k.split("__")
        arg_required = v
        template[arg_name] = (arg_type, arg_required)

    def method_func(method):
        def wrapper(*args, **kwargs):
            new_kwargs = {}
            new_kwargs.update(kwargs)

            for arg_name, (arg_type, arg_required) in template.items():
                if arg_required and arg_name not in new_kwargs:
                    raise Exception("Required argument: " + arg_name)
                elif not arg_required and arg_name not in new_kwargs:
                    continue

                new_kwargs[arg_name] = eval(arg_type)(kwargs[arg_name])

            return method(*args, **new_kwargs)

        return wrapper

    return method_func


@argument_validator(username__str=1, age__int=1, gender__int=0)
def my_view(**kwargs):
    print(kwargs)


if __name__ == '__main__':
    my_view(username="xxxx", age='7', gender="1", abc="sdf")


# def upper(method):
#     print("call upper")
#
#     def wrapper(*args, **kwargs):
#         new_args = []
#         new_kwargs = {}
#
#         for a in args:
#             if isinstance(a, str):
#                 new_args.append(a.upper())
#             else:
#                 new_args.append(a)
#
#         for key, value in kwargs.items():
#             if isinstance(value, str):
#                 new_kwargs[key] = value.upper()
#             else:
#                 new_kwargs[key] = value
#
#         return method(*new_args, **new_kwargs)
#
#     return wrapper

class upper:
    def __init__(self, method):
        self.method = method

    def __call__(self, *args, **kwargs):
        new_args = []
        new_kwargs = {}

        for a in args:
            if isinstance(a, str):
                new_args.append(a.upper())
            else:
                new_args.append(a)

        for key, value in kwargs.items():
            if isinstance(value, str):
                new_kwargs[key] = value.upper()
            else:
                new_kwargs[key] = value

        return self.method(*new_args, **new_kwargs)


def filter_name(method):
    print(method)

    def wrapper(*args, **kwargs):
        n_kwargs = {}
        for key, value in kwargs.items():
            if key != 'name':
                n_kwargs[key] = value
            else:
                print('已去除name字段，结果如下')
        return method(*args, **n_kwargs)

    return wrapper


def filter_name_ex(keywords):
    def wrapper(method):
        def func1(*args, **kwargs):
            for a in keywords:
                if a in kwargs.keys():
                    raise Exception("Invalid argument: " + a)
            return method(*args, **kwargs)

        return func1

    return wrapper


@filter_name_ex(["name", "gender"])
def func1(*args, **kwargs):
    print(args, kwargs)
    return "xyz"


# m = func1(1, 2, "hello", "str3", xxxxx="john")

# mode = "w", "a", "w+", "r"

import os


class File:
    def __init__(self, path):
        self.fd = os.open(path, os.O_RDONLY)

    def read(self, size):
        return os.read(self.fd, size)

    def close(self):
        os.close(self.fd)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()
        # return True


def open(path):
    return File(path)


# fp = open("./fs.py")
# print(fp.read(10))
# fp.close()

try:
    with open("./fs.py") as fp:
        raise Exception("with statement error")
        print(fp.read(10))
except Exception as er:
    import traceback

    traceback.print_exc()

# with File("./fs.py") as fp:
#     print(fp.read(10))
